package net.goutalk.glcs.module.erpModel.caseErpPurchase.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import net.goutalk.glcs.common.annotation.GlcsLog;
import net.goutalk.glcs.common.constant.GlobalConstant;
import net.goutalk.glcs.common.enums.YesOrNoEnum;
import net.goutalk.glcs.common.model.result.R;
import net.goutalk.glcs.common.utils.RedisUtil;
import net.goutalk.glcs.module.erpModel.caseErpLog.entity.CaseErpLog;
import net.goutalk.glcs.module.erpModel.caseErpLog.service.ICaseErpLogService;
import net.goutalk.glcs.module.erpModel.caseErpPurchase.dto.AddCaseErpPurchaseDto;
import net.goutalk.glcs.module.erpModel.caseErpPurchase.dto.PurchaseExportDto;
import net.goutalk.glcs.module.erpModel.caseErpPurchase.dto.UpdateCaseErpPurchaseDto;
import net.goutalk.glcs.module.erpModel.caseErpPurchase.entity.CaseErpPurchase;
import net.goutalk.glcs.module.erpModel.caseErpPurchase.entity.CaseErpPurchaseDetail;
import net.goutalk.glcs.module.erpModel.caseErpPurchase.service.ICaseErpPurchaseDetailService;
import net.goutalk.glcs.module.erpModel.caseErpPurchase.service.ICaseErpPurchaseService;
import net.goutalk.glcs.module.erpModel.caseErpPurchase.utils.DataUtil;
import net.goutalk.glcs.module.erpModel.caseErpPurchase.vo.*;
import net.goutalk.glcs.module.erpModel.caseErpSale.dto.CaseErpSalePageDto;
import net.goutalk.glcs.module.erpModel.caseErpStock.vo.InStoreLogVo;
import net.goutalk.glcs.module.erpModel.caseErpStock.vo.TicketLogVo;
import net.goutalk.glcs.module.erpModel.caseErpStore.entity.CaseErpStoreReceipt;
import net.goutalk.glcs.module.erpModel.caseErpStore.service.ICaseErpStoreReceiptService;
import net.goutalk.glcs.module.erpModel.caseErpSupplier.entity.CaseErpSupplier;
import net.goutalk.glcs.module.erpModel.caseErpSupplier.service.ICaseErpSupplierService;
import net.goutalk.glcs.module.organization.entity.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import net.goutalk.glcs.module.erpModel.caseErpSale.vo.LogExportVo;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 采购订单信息【case_erp_purchase】 前端控制器
 * </p>
 *
 * @author hnyyzy
 * @since 2023-06-21
 */
@RestController
@RequestMapping(GlobalConstant.CASE_ERP_PURCHASE +"/caseErpPurchase")
@Api(value = GlobalConstant.CASE_ERP_PURCHASE +"/caseErpSale", tags = "采购订单信息")
@AllArgsConstructor
public class CaseErpPurchaseController {

    private ICaseErpPurchaseService caseErpPurchaseService;

    private ICaseErpPurchaseDetailService caseErpPurchaseDetailService;

    private ICaseErpLogService caseErpLogService;

    private ICaseErpSupplierService caseErpSupplierService;

    private ICaseErpStoreReceiptService caseErpStoreReceiptService;

    private RedisUtil redisUtil;

    @GetMapping(value = "/list")
    @ApiOperation("采购订单信息列表")
    public R list(CaseErpSalePageDto dto) {
        List<CaseErpPurchase> list = caseErpPurchaseService.list(Wrappers.<CaseErpPurchase>query().lambda()
                .like(StrUtil.isNotBlank(dto.getTheme()),CaseErpPurchase::getTheme,dto.getTheme())
                .or()
                .like(StrUtil.isNotBlank(dto.getTheme()),CaseErpPurchase::getPurchaseNumber,dto.getTheme())
        );
        List<User> userList = redisUtil.get(GlobalConstant.USER_CACHE_KEY, new TypeReference<List<User>>() {
        });
        List<CaseErpPurchaseListVo> caseErpPurchaseListVos = BeanUtil.copyToList(list, CaseErpPurchaseListVo.class);
        for (CaseErpPurchaseListVo caseErpPurchaseListVo : caseErpPurchaseListVos) {
            if (ObjectUtil.isNotEmpty(caseErpPurchaseListVo.getCreateUserId())){
                final User user = userList.stream().filter(x -> x.getId().equals(caseErpPurchaseListVo.getCreateUserId())).findFirst().orElse(new User());
                if (StrUtil.isNotBlank(user.getName())){
                    caseErpPurchaseListVo.setCreateUserName(user.getName());
                }
            }
        }
        return R.ok(caseErpPurchaseListVos);
    }

    @GetMapping(value = "/page")
    @ApiOperation("采购订单信息列表分页")
    public R page(CaseErpSalePageDto dto) {
        return R.ok(caseErpPurchaseService.getPageList(dto));
    }

    @PostMapping
    @ApiOperation(value = "新增采购订单信息")
    @Transactional
    public R add(@RequestBody AddCaseErpPurchaseDto dto) {
        CaseErpPurchase caseErpPurchase = BeanUtil.toBean(dto, CaseErpPurchase.class);
        if (ObjectUtil.isNotEmpty(dto.getIsSysNumBoolean()) && dto.getIsSysNumBoolean()){
            caseErpPurchase.setIsSysNum(YesOrNoEnum.YES.getCode());
        }else {
            caseErpPurchase.setIsSysNum(YesOrNoEnum.NO.getCode());
        }
        if (ObjectUtil.isNotEmpty(dto.getIsRelationApplyBoolean()) && dto.getIsRelationApplyBoolean()){
            caseErpPurchase.setIsRelationApply(YesOrNoEnum.YES.getCode());
        }else {
            caseErpPurchase.setIsRelationApply(YesOrNoEnum.NO.getCode());
        }

        if (ObjectUtil.isNotEmpty(dto.getSupplierId())){
            CaseErpSupplier caseErpSupplier = caseErpSupplierService.getById(dto.getSupplierId());
            if (StrUtil.isNotBlank(caseErpSupplier.getName())){
                caseErpPurchase.setSupplierName(caseErpSupplier.getName());
            }
        }
        // 默认到票状态未完成
        caseErpPurchase.setTicketState(YesOrNoEnum.NO.getCode());
        // 默认付款状态未完成
        caseErpPurchase.setPayState(YesOrNoEnum.NO.getCode());
        //默认入库状态未完成
        caseErpPurchase.setInStoreState(YesOrNoEnum.NO.getCode());
        caseErpPurchase.setAlreadyAmount(BigDecimal.ZERO);
        caseErpPurchase.setAlreadyTicket(BigDecimal.ZERO);
        caseErpPurchaseService.save(caseErpPurchase);

        List<CaseErpPurchaseDetail> caseErpPurchaseDetails = BeanUtil.copyToList(dto.getAddCaseErpPurchaseDetailDtoList(), CaseErpPurchaseDetail.class);
        if (CollectionUtil.isNotEmpty(caseErpPurchaseDetails)) {
            caseErpPurchaseDetails.stream().forEach(detail -> {
                detail.setPurchaseId(caseErpPurchase.getId());
                detail.setInStoreCount(BigDecimal.ZERO);
                detail.setNoInStoreCount(BigDecimal.ZERO);
                detail.setReturnCount(BigDecimal.ZERO);
            });
            caseErpPurchaseDetailService.saveBatch(caseErpPurchaseDetails);
        }

        CaseErpLog log = new CaseErpLog();
        User user = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());
        log.setCategoryId(2);
        log.setOperateTime(LocalDateTime.now());
        log.setOperateUserId(user.getId());
        log.setOperateUserAccount(user.getName());
        log.setKeyId(caseErpPurchase.getId());
        log.setExecuteResultJson("新增采购订单");
        caseErpLogService.save(log);

        return R.ok(true);
    }

    @PutMapping
    @ApiOperation(value = "修改采购订单信息")
    @Transactional
    public R update(@Valid @RequestBody UpdateCaseErpPurchaseDto dto) {
        CaseErpPurchase caseErpPurchase = BeanUtil.toBean(dto, CaseErpPurchase.class);
        if (ObjectUtil.isNotEmpty(dto.getIsSysNumBoolean()) && dto.getIsSysNumBoolean()){
            caseErpPurchase.setIsSysNum(YesOrNoEnum.YES.getCode());
        }else {
            caseErpPurchase.setIsSysNum(YesOrNoEnum.NO.getCode());
        }
        if (ObjectUtil.isNotEmpty(dto.getIsRelationApplyBoolean()) && dto.getIsRelationApplyBoolean()){
            caseErpPurchase.setIsRelationApply(YesOrNoEnum.YES.getCode());
        }else {
            caseErpPurchase.setIsRelationApply(YesOrNoEnum.NO.getCode());
        }
        if (ObjectUtil.isNotEmpty(dto.getSupplierId())){
            CaseErpSupplier caseErpSupplier = caseErpSupplierService.getById(dto.getSupplierId());
            if (StrUtil.isNotBlank(caseErpSupplier.getName())){
                caseErpPurchase.setSupplierName(caseErpSupplier.getName());
            }
        }
        caseErpPurchaseService.updateById(caseErpPurchase);
        //先删除所有详情再新增
        if (CollectionUtil.isNotEmpty(dto.getAddCaseErpPurchaseDetailDtoList())){
            caseErpPurchaseDetailService.remove(Wrappers.lambdaQuery(CaseErpPurchaseDetail.class).eq(CaseErpPurchaseDetail::getPurchaseId, caseErpPurchase.getId()));

            List<CaseErpPurchaseDetail> caseErpPurchaseDetails = BeanUtil.copyToList(dto.getAddCaseErpPurchaseDetailDtoList(), CaseErpPurchaseDetail.class);
            if (CollectionUtil.isNotEmpty(caseErpPurchaseDetails)) {
                caseErpPurchaseDetails.stream().forEach(detail -> {
                    detail.setPurchaseId(caseErpPurchase.getId());
                    detail.setInStoreCount(BigDecimal.ZERO);
                    detail.setNoInStoreCount(BigDecimal.ZERO);
                    detail.setReturnCount(BigDecimal.ZERO);
                });
            }
            caseErpPurchaseDetailService.saveOrUpdateBatch(caseErpPurchaseDetails);
        }else {
            caseErpPurchaseDetailService.remove(Wrappers.lambdaQuery(CaseErpPurchaseDetail.class).eq(CaseErpPurchaseDetail::getPurchaseId, caseErpPurchase.getId()));
        }

        CaseErpLog log = new CaseErpLog();
        User user = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());
        log.setCategoryId(2);
        log.setOperateTime(LocalDateTime.now());
        log.setOperateUserId(user.getId());
        log.setOperateUserAccount(user.getName());
        log.setKeyId(caseErpPurchase.getId());
        log.setExecuteResultJson("修改采购订单");
        caseErpLogService.save(log);
        return R.ok(true);
    }

    @GetMapping(value = "/info")
    @ApiOperation(value = "根据id查询采购订单信息（返回id值，编辑使用）")
    public R info(@RequestParam Long id) {
        CaseErpPurchase caseErpPurchase = caseErpPurchaseService.getById(id);
        if (caseErpPurchase == null) {
            R.error("找不到此采购订单信息！");
        }
        CaseErpPurchaseInfoVo caseErpPurchaseInfoVo = BeanUtil.toBean(caseErpPurchase, CaseErpPurchaseInfoVo.class);
        if (ObjectUtil.isNotEmpty(caseErpPurchaseInfoVo.getIsRelationApply()) && caseErpPurchaseInfoVo.getIsRelationApply() == YesOrNoEnum.YES.getCode()){
            caseErpPurchaseInfoVo.setIsRelationApplyBoolean(true);
        }else {
            caseErpPurchaseInfoVo.setIsRelationApplyBoolean(false);
        }
        if (ObjectUtil.isNotEmpty(caseErpPurchaseInfoVo.getIsSysNum()) && caseErpPurchaseInfoVo.getIsSysNum() == YesOrNoEnum.YES.getCode()){
            caseErpPurchaseInfoVo.setIsSysNumBoolean(true);
        }else {
            caseErpPurchaseInfoVo.setIsSysNumBoolean(false);
        }
        List<CaseErpPurchaseDetail> list = caseErpPurchaseDetailService.list(Wrappers.<CaseErpPurchaseDetail>query().lambda().eq(CaseErpPurchaseDetail::getPurchaseId, caseErpPurchase.getId()));
        caseErpPurchaseInfoVo.setCaseErpPurchaseDetails(list);
        return R.ok(caseErpPurchaseInfoVo);
    }

    @DeleteMapping
    @ApiOperation(value = "删除")
    @GlcsLog(value = "删除采购订单信息")
    public R delete(@Valid @RequestBody Long id) {
        caseErpPurchaseService.removeById(id);
        caseErpPurchaseDetailService.remove(Wrappers.<CaseErpPurchaseDetail>query().lambda().eq(CaseErpPurchaseDetail::getPurchaseId,id));
        return R.ok(true);
    }

    @PostMapping(value = "/export")
    @ApiOperation(value = "导出")
    @GlcsLog(value = "导出表单数据")
    public ResponseEntity<byte[]> export(@RequestBody List<Long> ids) {
        List<CaseErpPurchasePageVo> caseErpPurchasePageVos = caseErpPurchaseService.importByIds(ids);
        List<CaseErpPurchaseExportVo> saleExportVoList = BeanUtil.copyToList(caseErpPurchasePageVos, CaseErpPurchaseExportVo.class);
        ByteArrayOutputStream bot = new ByteArrayOutputStream();
        EasyExcel.write(bot, CaseErpPurchaseExportVo.class).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(saleExportVoList);
        return R.fileStream(bot.toByteArray(), "采购订单列表" + ExcelTypeEnum.XLSX.getValue());
    }

    @GetMapping(value = "/check-info")
    @ApiOperation(value = "根据id查询采购订单信息（返回id值，供查看使用）")
    public R checkInfo(@RequestParam Long id) {
        return R.ok(caseErpPurchaseService.checkInfo(id));
    }


    @PostMapping(value = "/export-purchase-detail")
    @ApiOperation(value = "导出采购详情数据")
    @GlcsLog(value = "导出表单数据")
    public ResponseEntity<byte[]> exportCaseErpPurchaseDetail(@RequestBody PurchaseExportDto dto) {
        List<CaseErpPurchaseDetail> saledetailList = caseErpPurchaseDetailService.list(Wrappers.lambdaQuery(CaseErpPurchaseDetail.class).in(CaseErpPurchaseDetail::getId, dto.getIds()));
        List<CaseErpPurchaseDetailExportVo> saleExportVoList = BeanUtil.copyToList(saledetailList, CaseErpPurchaseDetailExportVo.class);
        ByteArrayOutputStream bot = new ByteArrayOutputStream();
        EasyExcel.write(bot, CaseErpPurchaseDetailExportVo.class).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(saleExportVoList);
        return R.fileStream(bot.toByteArray(), "产品明细列表" + ExcelTypeEnum.XLSX.getValue());
    }

    @PostMapping(value = "/export-purchase-in")
    @ApiOperation(value = "导出采购入库数据")
    @GlcsLog(value = "导出表单数据")
    public ResponseEntity<byte[]> exportCaseErpPurchaseIn(@RequestBody PurchaseExportDto dto) {
        //拿订单的id去出入库单据表查询，有无关联数据，有的话就展示
        List<InStoreLogVo> inStoreLogVos = new ArrayList<>();
        List<CaseErpStoreReceipt> list = caseErpStoreReceiptService.list(Wrappers.<CaseErpStoreReceipt>query().lambda().eq(CaseErpStoreReceipt::getRelationKeyId, dto.getPurchaseId()));
        if (CollectionUtil.isNotEmpty(list)) {//真数据
            for (CaseErpStoreReceipt caseErpStoreReceipt : list) {
                InStoreLogVo inStoreLogVo = new InStoreLogVo();
                inStoreLogVo.setId(caseErpStoreReceipt.getId());
                inStoreLogVo.setCode(caseErpStoreReceipt.getCode());
                inStoreLogVo.setTheme(caseErpStoreReceipt.getName());
                inStoreLogVo.setDate(caseErpStoreReceipt.getCreateDate());
                inStoreLogVo.setName("客户一");
                inStoreLogVo.setPerson(caseErpStoreReceipt.getPersonNames());
                inStoreLogVo.setStore("仓库一");
                inStoreLogVos.add(inStoreLogVo);
            }
        }
        List<InStoreLogVo> collect = inStoreLogVos.stream().filter(x -> dto.getIds().contains(x.getId())).collect(Collectors.toList());
        List<InStoreLogExportVo> saleExportVoList = BeanUtil.copyToList(collect, InStoreLogExportVo.class);
        ByteArrayOutputStream bot = new ByteArrayOutputStream();
        EasyExcel.write(bot, InStoreLogExportVo.class).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(saleExportVoList);
        return R.fileStream(bot.toByteArray(), "采购入库记录列表" + ExcelTypeEnum.XLSX.getValue());
    }

    @PostMapping(value = "/export-purchase-ticket")
    @ApiOperation(value = "导出采购订单到票记录")
    @GlcsLog(value = "导出表单数据")
    public ResponseEntity<byte[]> exportCaseErpPurchaseTicket(@RequestBody PurchaseExportDto dto) {
        List<TicketLogVo> ticketLogVos = DataUtil.buildTicketLogList(dto.getPurchaseId());
        List<TicketLogVo> collect = ticketLogVos.stream().filter(x -> dto.getIds().contains(x.getId())).collect(Collectors.toList());
        List<TicketLogExportVo> saleExportVoList = BeanUtil.copyToList(collect, TicketLogExportVo.class);
        ByteArrayOutputStream bot = new ByteArrayOutputStream();
        EasyExcel.write(bot, TicketLogExportVo.class).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(saleExportVoList);
        return R.fileStream(bot.toByteArray(), "采购订单到票记录列表" + ExcelTypeEnum.XLSX.getValue());
    }


    @PostMapping(value = "/export-purchase-pay")
    @ApiOperation(value = "导出采购订单付款记录")
    @GlcsLog(value = "导出表单数据")
    public ResponseEntity<byte[]> exportCaseErpPurchasePay(@RequestBody PurchaseExportDto dto) {
        List<PayLogVo> payLogVos = DataUtil.buildPayLogList(dto.getPurchaseId());
        List<PayLogVo> collect = payLogVos.stream().filter(x -> dto.getIds().contains(x.getId())).collect(Collectors.toList());
        List<PayLogExportVo> saleExportVoList = BeanUtil.copyToList(collect, PayLogExportVo.class);
        ByteArrayOutputStream bot = new ByteArrayOutputStream();
        EasyExcel.write(bot, PayLogExportVo.class).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(saleExportVoList);
        return R.fileStream(bot.toByteArray(), "采购订单付款记录列表" + ExcelTypeEnum.XLSX.getValue());
    }

    @PostMapping(value = "/export-purchase-log")
    @ApiOperation(value = "导出采购操作记录数据")
    @GlcsLog(value = "导出表单数据")
    public ResponseEntity<byte[]> exportCaseErpPurchaseLog(@RequestBody PurchaseExportDto dto) {
        List<CaseErpLog> logList = caseErpLogService.list(Wrappers.lambdaQuery(CaseErpLog.class).in(CaseErpLog::getId, dto.getIds()));
        List<User> userList = redisUtil.get(GlobalConstant.USER_CACHE_KEY, new TypeReference<List<User>>() {
        });
        for (CaseErpLog caseErpLog : logList) {
            if (ObjectUtil.isNotEmpty(caseErpLog.getCreateUserId())){
                User user = userList.stream().filter(x -> x.getId().equals(caseErpLog.getCreateUserId())).findFirst().orElse(new User());
                if (StrUtil.isNotBlank(user.getName())){
                    caseErpLog.setOperateUserAccount(user.getName());
                }
            }
        }
        List<LogExportVo> saleExportVoList = BeanUtil.copyToList(logList, LogExportVo.class);
        ByteArrayOutputStream bot = new ByteArrayOutputStream();
        EasyExcel.write(bot, LogExportVo.class).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(saleExportVoList);
        return R.fileStream(bot.toByteArray(), "采购操作记录列表" + ExcelTypeEnum.XLSX.getValue());
    }
}
